/**
 * 中文时间工具封装 (zh-timer.js)
 * 支持倒计时、间隔执行、链式控制：.开始()、.暂停()、.重置()
 * 中文方法命名 + JSDoc 参数提示
 */

class 计时器 {
  /**
   * 构造函数 - 创建计时器实例
   * @param {number} [时长=1000] 计时时长（毫秒）
   * @param {Object} [选项={}] 配置选项
   * @param {boolean} [选项.自动开始=false] 是否自动开始计时
   * @param {boolean} [选项.循环=false] 是否循环执行
   * @param {boolean} [选项.立即执行=false] 是否立即执行回调
   */
  constructor(时长 = 1000, 选项 = {}) {
    this._时长 = Math.max(0, Number(时长) || 1000);
    this._选项 = {
      自动开始: false,
      循环: false,
      立即执行: false,
      ...选项
    };
    
    this._定时器ID = null;
    this._开始时间 = null;
    this._剩余时间 = this._时长;
    this._状态 = '已停止'; // 已停止、运行中、暂停中
    this._回调 = null;
    this._完成回调 = null;
    this._更新回调 = null;
    this._暂停时间 = null;
    this._累计暂停时间 = 0;
    
    if (this._选项.自动开始) {
      this.开始();
    }
  }

  /**
   * 获取计时器的当前状态
   * @returns {string} 状态字符串：'已停止'、'运行中'或'暂停中'
   */
  获取状态() {
    return this._状态;
  }

  /**
   * 获取剩余时间（毫秒）
   * @returns {number} 剩余时间（毫秒）
   */
  获取剩余时间() {
    if (this._状态 === '运行中') {
      const 当前时间 = Date.now();
      return Math.max(0, this._剩余时间 - (当前时间 - this._开始时间 - this._累计暂停时间));
    }
    return this._剩余时间;
  }

  /**
   * 获取已经经过的时间（毫秒）
   * @returns {number} 经过时间（毫秒）
   */
  获取经过时间() {
    return this._时长 - this._剩余时间;
  }

  /**
   * 设置计时结束时的回调函数
   * @param {Function} 函数 回调函数，接收计时器实例作为参数
   * @returns {计时器} 返回this以支持链式调用
   */
  回调(函数) {
    if (typeof 函数 === 'function') {
      this._回调 = 函数;
    }
    return this;
  }

  /**
   * 设置计时完成时的回调函数
   * @param {Function} 函数 回调函数，接收计时器实例作为参数
   * @returns {计时器} 返回this以支持链式调用
   */
  完成回调(函数) {
    if (typeof 函数 === 'function') {
      this._完成回调 = 函数;
    }
    return this;
  }

  /**
   * 设置更新回调函数
   * @param {Function} 函数 更新回调函数，在倒计时模式下每秒调用一次
   * @returns {计时器} 返回this以支持链式调用
   */
  更新回调(函数) {
    if (typeof 函数 === 'function') {
      this._更新回调 = 函数;
    }
    return this;
  }

  /**
   * 开始或继续计时
   * @returns {计时器} 返回this以支持链式调用
   */
  开始() {
    if (this._状态 === '运行中') return this;
    
    if (this._状态 === '暂停中') {
      // 从暂停处继续
      this._累计暂停时间 += Date.now() - this._暂停时间;
      this._状态 = '运行中';
      
      this._定时器ID = setTimeout(() => {
        this._执行回调();
      }, this._剩余时间);
    } else {
      // 新开始
      this._开始时间 = Date.now();
      this._暂停时间 = null;
      this._累计暂停时间 = 0;
      this._状态 = '运行中';
      
      // 如果设置了立即执行
      if (this._选项.立即执行 && this._回调) {
        this._回调(this);
      }
      
      this._定时器ID = setTimeout(() => {
        this._执行回调();
      }, this._时长);
    }
    
    return this;
  }

  /**
   * 暂停计时
   * @returns {计时器} 返回this以支持链式调用
   */
  暂停() {
    if (this._状态 !== '运行中') return this;
    
    clearTimeout(this._定时器ID);
    this._暂停时间 = Date.now();
    this._剩余时间 = this._剩余时间 - (this._暂停时间 - this._开始时间 - this._累计暂停时间);
    this._状态 = '暂停中';
    
    return this;
  }

  /**
   * 停止计时并重置状态
   * @returns {计时器} 返回this以支持链式调用
   */
  停止() {
    clearTimeout(this._定时器ID);
    this._状态 = '已停止';
    this._剩余时间 = this._时长;
    this._开始时间 = null;
    this._暂停时间 = null;
    this._累计暂停时间 = 0;
    
    return this;
  }

  /**
   * 重置计时器并重新开始
   * @returns {计时器} 返回this以支持链式调用
   */
  重置() {
    return this.停止().开始();
  }

  /**
   * @private
   * 内部方法：执行回调函数
   */
  _执行回调() {
    // 执行主回调
    if (this._回调) {
      try {
        this._回调(this);
      } catch (错误) {
        console.error('定时器回调执行错误:', 错误);
      }
    }
    
    // 执行完成回调
    if (this._完成回调) {
      try {
        this._完成回调(this);
      } catch (错误) {
        console.error('定时器完成回调执行错误:', 错误);
      }
    }
    
    // 检查是否循环
    if (this._选项.循环) {
      this._重置并重新开始();
    } else {
      this._状态 = '已停止';
      this._剩余时间 = this._时长;
    }
  }

  /**
   * @private
   * 内部方法：重置并重新开始计时
   */
  _重置并重新开始() {
    this._开始时间 = Date.now();
    this._累计暂停时间 = 0;
    this._定时器ID = setTimeout(() => {
      this._执行回调();
    }, this._时长);
  }

  /** 静态方法 */

  /**
   * 静态方法：创建计时器实例
   * @static
   * @param {number} 时长 计时时长（毫秒）
   * @param {Object} 选项 配置选项
   * @returns {计时器} 计时器实例
   */
  static 创建(时长, 选项) {
    return new 计时器(时长, 选项);
  }

  /**
   * 静态方法：创建倒计时器实例
   * @static
   * @param {number} 秒数 倒计时秒数
   * @param {Object} [选项={}] 配置选项
   * @returns {计时器} 倒计时器实例
   */
  static 倒计时(秒数, 选项 = {}) {
    const 倒计时器 = new 计时器(秒数 * 1000, {
      循环: false,
      ...选项
    });
    
    let _更新定时器 = null;
    let _最后更新时间 = null;
    
    // 重写开始方法以添加每秒更新
    const 原始开始 = 倒计时器.开始;
    倒计时器.开始 = function() {
      _最后更新时间 = Date.now();
      
      // 设置每秒更新
      if (倒计时器._更新回调) {
        _更新定时器 = setInterval(() => {
          if (倒计时器._状态 === '运行中') {
            const 剩余秒数 = Math.max(0, Math.ceil(倒计时器._剩余时间 / 1000));
            倒计时器._更新回调(剩余秒数, 倒计时器);
          }
        }, 1000);
      }
      
      return 原始开始.call(this);
    };
    
    // 重写暂停方法
    const 原始暂停 = 倒计时器.暂停;
    倒计时器.暂停 = function() {
      if (_更新定时器) {
        clearInterval(_更新定时器);
      }
      return 原始暂停.call(this);
    };
    
    // 重写停止方法
    const 原始停止 = 倒计时器.停止;
    倒计时器.停止 = function() {
      if (_更新定时器) {
        clearInterval(_更新定时器);
      }
      return 原始停止.call(this);
    };
    
    return 倒计时器;
  }

  /**
   * 静态方法：创建间隔执行器实例
   * @static
   * @param {number} 间隔毫秒 执行间隔（毫秒）
   * @param {Object} [选项={}] 配置选项
   * @returns {计时器} 间隔执行器实例
   */
  static 间隔执行(间隔毫秒, 选项 = {}) {
    return new 计时器(间隔毫秒, {
      循环: true,
      立即执行: false,
      ...选项
    });
  }

  /**
   * 静态方法：创建并启动延迟执行器
   * @static
   * @param {number} 延迟毫秒 延迟时间（毫秒）
   * @param {Function} 回调 延迟后执行的回调函数
   * @returns {计时器} 已启动的延迟执行器实例
   */
  static 延迟(延迟毫秒, 回调) {
    const 定时器 = new 计时器(延迟毫秒);
    if (回调) {
      定时器.回调(回调);
    }
    return 定时器.开始();
  }
}

/**
 * 秒表类 - 用于计时和计次功能
 */
 class 秒表 {
  /**
   * 构造函数 - 创建秒表实例
   */
  constructor() {
    this._开始时间 = null;
    this._暂停开始时间 = null;
    this._累计暂停时间 = 0;
    this._状态 = '已停止'; // 已停止、运行中、暂停中
    this._计次记录 = [];
  }

  /**
   * 开始或继续计时
   * @returns {秒表} 返回this以支持链式调用
   */
  开始() {
    if (this._状态 === '运行中') return this;
    
    if (this._状态 === '暂停中') {
      // 从暂停处继续
      this._累计暂停时间 += Date.now() - this._暂停开始时间;
    } else {
      // 新开始
      this._开始时间 = Date.now();
    }
    
    this._状态 = '运行中';
    return this;
  }

  /**
   * 暂停计时
   * @returns {秒表} 返回this以支持链式调用
   */
  暂停() {
    if (this._状态 !== '运行中') return this;
    
    this._暂停开始时间 = Date.now();
    this._状态 = '暂停中';
    return this;
  }

  /**
   * 停止计时并重置所有状态
   * @returns {秒表} 返回this以支持链式调用
   */
  停止() {
    this._状态 = '已停止';
    this._开始时间 = null;
    this._暂停开始时间 = null;
    this._累计暂停时间 = 0;
    this._计次记录 = [];
    return this;
  }

  /**
   * 重置秒表但保持当前状态
   * @returns {秒表} 返回this以支持链式调用
   */
  重置() {
    const 当前状态 = this._状态;
    this._计次记录 = [];
    
    if (this._状态 === '运行中') {
      this._开始时间 = Date.now();
      this._累计暂停时间 = 0;
    } else if (this._状态 === '暂停中') {
      this._累计暂停时间 = 0;
    }
    
    return this;
  }

  /**
   * 记录当前计次时间
   * @returns {number|null} 当前计次时间（毫秒），如果秒表已停止则返回null
   */
  计次() {
    if (this._状态 === '已停止') return null;
    
    const 计次时间 = this._获取经过时间();
    this._计次记录.push(计次时间);
    return 计次时间;
  }

  /**
   * 获取经过时间（毫秒）
   * @returns {number} 经过时间（毫秒）
   */
  获取经过时间() {
    return this._获取经过时间();
  }

  /**
   * 获取经过时间的格式化字符串
   * @param {string} [格式='HH:mm:ss.SSS'] 时间格式模板
   * @returns {string} 格式化的时间字符串
   */
  获取经过时间格式化(格式 = 'HH:mm:ss.SSS') {
    const 毫秒 = this._获取经过时间();
    return this._格式化时间(毫秒, 格式);
  }

  /**
   * 获取所有计次记录
   * @returns {Array<number>} 计次时间数组（毫秒）
   */
  获取计次记录() {
    return [...this._计次记录];
  }

  /**
   * 获取秒表当前状态
   * @returns {string} 状态字符串：'已停止'、'运行中'或'暂停中'
   */
  获取状态() {
    return this._状态;
  }

  /**
   * @private
   * 内部方法：获取经过时间
   * @returns {number} 经过时间（毫秒）
   */
  _获取经过时间() {
    if (this._状态 === '已停止' || !this._开始时间) {
      return 0;
    }
    
    let 当前时间 = Date.now();
    if (this._状态 === '暂停中') {
      当前时间 = this._暂停开始时间;
    }
    
    return 当前时间 - this._开始时间 - this._累计暂停时间;
  }

  /**
   * @private
   * 内部方法：格式化时间
   * @param {number} 毫秒 毫秒数
   * @param {string} 格式 时间格式模板
   * @returns {string} 格式化的时间字符串
   */
  _格式化时间(毫秒, 格式) {
    const 总秒数 = Math.floor(毫秒 / 1000);
    const 小时 = Math.floor(总秒数 / 3600);
    const 分钟 = Math.floor((总秒数 % 3600) / 60);
    const 秒数 = 总秒数 % 60;
    const 毫秒数 = Math.floor(毫秒 % 1000);
    
    return 格式
      .replace('HH', 小时.toString().padStart(2, '0'))
      .replace('mm', 分钟.toString().padStart(2, '0'))
      .replace('ss', 秒数.toString().padStart(2, '0'))
      .replace('SSS', 毫秒数.toString().padStart(3, '0'));
  }
}

/**
 * 定时器管理器类 - 用于管理多个定时器实例
 */
 class 定时器管理器 {
  constructor() {
    this._定时器列表 = new Map();
  }

  /**
   * 添加定时器到管理器
   * @param {string|symbol} 名称 定时器标识
   * @param {计时器|秒表} 定时器 定时器实例
   * @returns {定时器管理器} 返回this以支持链式调用
   */
  添加定时器(名称, 定时器) {
    this._定时器列表.set(名称, 定时器);
    return this;
  }

  /**
   * 获取指定名称的定时器
   * @param {string|symbol} 名称 定时器标识
   * @returns {计时器|秒表|null} 定时器实例或null
   */
  获取定时器(名称) {
    return this._定时器列表.get(名称);
  }

  /**
   * 开始指定名称的定时器
   * @param {string|symbol} 名称 定时器标识
   * @returns {定时器管理器} 返回this以支持链式调用
   */
  开始定时器(名称) {
    const 定时器 = this._定时器列表.get(名称);
    if (定时器) {
      定时器.开始();
    }
    return this;
  }

  /**
   * 暂停指定名称的定时器
   * @param {string|symbol} 名称 定时器标识
   * @returns {定时器管理器} 返回this以支持链式调用
   */
  暂停定时器(名称) {
    const 定时器 = this._定时器列表.get(名称);
    if (定时器) {
      定时器.暂停();
    }
    return this;
  }

  /**
   * 停止指定名称的定时器
   * @param {string|symbol} 名称 定时器标识
   * @returns {定时器管理器} 返回this以支持链式调用
   */
  停止定时器(名称) {
    const 定时器 = this._定时器列表.get(名称);
    if (定时器) {
      定时器.停止();
    }
    return this;
  }

  /**
   * 移除指定名称的定时器
   * @param {string|symbol} 名称 定时器标识
   * @returns {定时器管理器} 返回this以支持链式调用
   */
  移除定时器(名称) {
    const 定时器 = this._定时器列表.get(名称);
    if (定时器) {
      定时器.停止();
    }
    this._定时器列表.delete(名称);
    return this;
  }

  /**
   * 开始所有定时器
   * @returns {定时器管理器} 返回this以支持链式调用
   */
  开始所有定时器() {
    this._定时器列表.forEach(定时器 => 定时器.开始());
    return this;
  }

  /**
   * 暂停所有定时器
   * @returns {定时器管理器} 返回this以支持链式调用
   */
  暂停所有定时器() {
    this._定时器列表.forEach(定时器 => 定时器.暂停());
    return this;
  }

  /**
   * 停止所有定时器
   * @returns {定时器管理器} 返回this以支持链式调用
   */
  停止所有定时器() {
    this._定时器列表.forEach(定时器 => 定时器.停止());
    return this;
  }

  /**
   * 清空所有定时器
   * @returns {定时器管理器} 返回this以支持链式调用
   */
  清空所有定时器() {
    this._定时器列表.forEach(定时器 => 定时器.停止());
    this._定时器列表.clear();
    return this;
  }
}



// CommonJS 导出

  module.exports = {
    计时器,
    秒表,
    定时器管理器,
    default: 计时器
  };
  module.exports.计时器 = 计时器;
  module.exports.秒表 = 秒表;
  module.exports.定时器管理器 = 定时器管理器;


// ES 模块导出
// export { 计时器, 秒表, 定时器管理器 };
// export default 计时器;